﻿using System;
using System.Web.Mvc;
using NUnit.Framework;
using WeBlog.Controllers;
using WeBlog.DataContext;
using WeBlog.Interfaces;
using WeBlog.Models;
using WeBlog.Repositories;
using WeBlog.Services;
using WeBlog.Tests.Helpers;
using WeBlog.Tests.Mocks;

namespace WeBlog.Tests.Controllers
{
    [TestFixture]
    public class PageControllerTests
    {
        private IUnitOfWork _unitOfWork;

        [SetUp]
        public void Setup()
        {
            _unitOfWork = new InMemoryUnitOfWork();

            var repository = new PageRepository(_unitOfWork);
            var page = new Page { PageId = 10, Title = "Hello", Description = "Hello Description", Slug = "Hello" }; 
            var page2 = new Page { PageId = 20, Title = "Goodbye", Description = "Goodbye Description", Slug = "Goodbye" };
            repository.Add(page);
            repository.Add(page2);
        }

        [Test]
        public void Create_Action_Should_Return_Correct_Model()
        {
            //Arrange
            var controller = new PageController(_unitOfWork);

            //Act
            var result = controller.Create() as ViewResult;

            //Assert
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOf(typeof(PageFormViewModel), result.ViewData.Model);
        }

        [Test]
        public void Create_Action_Should_Insert_Data_When_Input_Is_Valid()
        {
            //Arrange
            var controller = new PageController(_unitOfWork);
            var page = new Page { PageId = 1, Title="MyPage", Description="MyDescription", Content="MyPageContent", Published=true, PublishDate=DateTime.Parse("2011-04-15")};

            //Act
            var result = controller.Create(page) as RedirectToRouteResult;

            //Assert
            var testPage = new PageRepository(_unitOfWork).Find(1);
            Assert.IsNotNull(result);
            Assert.AreEqual("Edit", result.RouteValues["action"]);
            Assert.IsNotNull(testPage);
            Assert.AreEqual("MyPage", testPage.Title);
            Assert.AreEqual("MyDescription", testPage.Description);
        }

        [Test]
        public void Delete_Action_Should_Remove_Data_When_Input_Is_Valid()
        {
             //Arrange
            var controller = new PageController(_unitOfWork);

            //Act
            var result = controller.Delete(10) as JsonResult;

            //Assert
            Assert.IsTrue((result.Data as JsonResponse).Success);
            Assert.IsNull(new PageRepository(_unitOfWork).Find(10));
        }

        [Test]
        public void Delete_Action_Should_Fail_When_UnitOfWork_Is_Null()
        {
            //Arrange
            var controller = new PageController(null);

            //Act
            var result = controller.Delete(10) as JsonResult;

            //Assert
            Assert.IsFalse((result.Data as JsonResponse).Success);
        }

        [Test]
        public void Details_Action_Should_Return_Valid_Model()
        {
            //Arrange
            var controller = new PageController(_unitOfWork);

            //Act
            var result = controller.Details("Hello") as ViewResult;

            //Assert
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOf(typeof(PageFormViewModel), result.ViewData.Model);
        }

        [Test]
        public void Details_Action_Throw_NotFound_Exception_When_Input_Is_Invalid()
        {
            //Arrange
            var controller = new PageController(_unitOfWork);

            //Act

            //Assert
            Assert.Throws(typeof(NotFoundException), () => controller.Details("Test"));
        }

        [Test]
        public void Edit_Action_Should_Return_Correct_Model()
        {
            //Arrange
            var controller = new PageController(_unitOfWork);

            //Act
            var result = controller.Edit(20) as ViewResult;

            //Assert
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOf(typeof(PageFormViewModel), result.ViewData.Model);
        }

        [Test]
        public void Edit_Action_Should_Update_Data_When_Input_Is_Valid()
        {
            //Arrange
            var controller = new PageController(_unitOfWork);
            var page = new PageRepository(_unitOfWork).Find(20);
            page.Title = "NewTitle";

            //Act
            var result = controller.Edit(page) as ViewResult;

            //Assert
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOf(typeof(PageFormViewModel), result.ViewData.Model);
            Assert.AreEqual("NewTitle", new PageRepository(_unitOfWork).Find(20).Title);
        }

        [Test]
        public void Manage_Action_Should_Return_Valid_Model()
        {
            //Arrange
            var controller = new PageController(_unitOfWork);
            controller.SetFakeControllerContext();

            //Act
            var result = controller.Manage(new GridSettings("Title")) as ViewResult;

            //Assert
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOf(typeof(PageListViewModel), result.ViewData.Model);
        }
    }
}